using UnityEngine;
using UnityEngine.Rendering;
using static UnityEngine.ParticleSystem;
using System.Collections.Generic;
using System;
using UnityEngine.Profiling;

public class ParticleSystemDummy : MonoBehaviour
{
    public ParticleDummyData Data{
        get
        {
            return ParticleDummyManager.Instance.GetParticleData(particleDataID);
        }
    }

    [SerializeField]
    private ulong particleDataID = 0;

    [SerializeField]
    Transform particleContent;

    [SerializeField]
    Vector3 initScale;

    public ParticleSystem CurrentParticle
    {
        get
        {
            if (poolNode == null)
            {
                return null;
            }
            return poolNode.ParticleSystem;
        }
    }

    ParticleSystemPoolNode poolNode;

    // 获取Tag会有GC，所以在这里缓存并序列化
    [SerializeField]
    string Tag = null;

    // 调用这个方法会初始化粒子数据，通常只有对象池中的母本需要调用一次，之后的克隆体会根据序列化进去的hashCode使用母本的数据
    public void InitParticleData()
    {
        // 在第一次调用，之后如果被Clone会直接使用已经序列化的参数，不再初始化一次
        if (particleDataID == 0 && TryGetComponent<ParticleSystem>(out var ps))
        {
            // 使用哈希值作为ID
            particleDataID = ParticleSystemHasher.ComputeParticleHash(ps);
            particleContent = new GameObject("ParticleContent").transform;
            particleContent.SetParent(this.transform);
            particleContent.localPosition = Vector3.zero;
            particleContent.localScale = Vector3.one;
            particleContent.localRotation = Quaternion.identity;
            particleContent.gameObject.layer = this.gameObject.layer;
            particleContent.gameObject.tag = this.gameObject.tag;

            // 记录一些必要的渲染参数，因为这些参数实时获取会比较耗或者有GC
            Tag = gameObject.tag;

#if UNITY_EDITOR
            if (ps.main.prewarm)
            {
                Debug.LogError($"粒子系统 {this.gameObject.name} 启用了预热功能，这可能会影响性能。请考虑关闭该功能。", this.gameObject);
            }
#endif

            ParticleDummyManager.Instance.RecordParticleData(particleDataID, ps);

            var renderer = ps.GetComponent<ParticleSystemRenderer>();
            DestroyImmediate(ps);
            DestroyImmediate(renderer);

            initScale = this.transform.localScale;

            if (this.gameObject.activeInHierarchy)
            {
                OnEnable();
            }
        }
    }

    public void OnEnable()
    {
        if (particleDataID != 0)
        {
            Transform nakedParticle;
            // 除非是在其他场景进行调试，否则总是应该使用对象池
            if (ParticleSystemDummyRoot.UsePool)
            {
                poolNode = ParticleSystemPool.Instance.Get(particleDataID);
                nakedParticle = poolNode.ParticleTransform;
            }
            else
            {
                nakedParticle = new GameObject().transform;
                var node = nakedParticle.gameObject.AddComponent<ParticleSystemPoolNode>();
                var particle = nakedParticle.gameObject.AddComponent<ParticleSystem>();
                node.ParticleSystem = particle;
            }

            nakedParticle.SetParent(this.particleContent, false);

            nakedParticle.gameObject.SetActive(true);
            nakedParticle.gameObject.layer = this.gameObject.layer;
            nakedParticle.gameObject.tag = Tag;

            CurrentParticle.Stop(false, ParticleSystemStopBehavior.StopEmittingAndClear);

            Profiler.BeginSample("ManagerApplyParticleData");
            ParticleDummyManager.Instance.ApplyParticleData(particleDataID, poolNode, initScale);
            Profiler.EndSample();
            
            CurrentParticle.Play();
        }
    }

    public void OnDisable()
    {
        if (poolNode)
        {
            if (ParticleSystemDummyRoot.UsePool)
            {
                ParticleSystemPool.Instance.Put(poolNode);
                poolNode = null;
            }
            else
            {
                DestroyImmediate(poolNode.gameObject);
                poolNode = null;
            }
        }
    }
}
